﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.PhilChuang.Mobile.Apps.LocationSender.Ui.Views;
using Com.PhilChuang.Pmvp.Model.Services;
using Com.PhilChuang.Utils;

namespace Com.PhilChuang.Mobile.Apps.LocationSender.Ui.Presenters
{
	public class SelectContactsPresenter : AbstractLocationSenderAppPresenter<ISelectContactsView>
	{
		#region Constants
		private const String RECIPIENTS = "SelectContactsPresenter.RECIPIENTS";
		#endregion

		#region Private members
		private IList<String> m_Recipients;
		private ITransientAppStateService m_TransientState;
		#endregion

		#region Constructors / Dispose
		public SelectContactsPresenter () : this (AppServiceLocator.Instance.GetImpl<ISelectContactsView> ())
		{
		}

		public SelectContactsPresenter (ISelectContactsView view) : base (view)
		{
			m_TransientState = AppServiceLocator.Instance.GetImpl<ITransientAppStateService> ();
		}
		#endregion

		#region AbstractPresenter implementation
		/// <summary>
		/// Subscribe to View events after the View is registered during Presenter instantiation.
		/// Call base impl as the first step.
		/// </summary>
		protected override void SubscribeToViewEvents ()
		{
			base.SubscribeToViewEvents ();

			View.DoReloadData += OnDoReloadData;
			View.DoSelectCoordsFormat += OnDoSelectCoordsFormat;
		}

		/// <summary>
		/// Unsubscribes to View events after the View has Closed.
		/// Call base impl as the first step.
		/// </summary>
		protected override void UnsubscribeFromViewEvents ()
		{
			base.UnsubscribeFromViewEvents ();

			View.DoReloadData -= OnDoReloadData;
			View.DoSelectCoordsFormat -= OnDoSelectCoordsFormat;
		}

		protected override void RefreshData ()
		{
			base.RefreshData ();

			if (m_Recipients.IsNullOrEmpty ())
				m_Recipients = (App.GetLastRecipients () ?? Enumerable.Empty<String> ()).ToList ();
		}

		/// <summary>
		/// Updates the View with Presenter data.
		/// Call base impl as the last step.
		/// </summary>
		protected override void UpdateToView ()
		{
			View.Recipients = m_Recipients;

			base.UpdateToView ();
		}

		/// <summary>
		/// Updates the Presenter with View data.
		/// Call base impl as the last step.
		/// </summary>
		protected override void UpdateFromView ()
		{
			m_Recipients = View.Recipients;

			base.UpdateFromView ();
		}

		/// <summary>
		/// Fires when the View is trying to Close.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected override void OnDoClose (object sender, System.ComponentModel.CancelEventArgs e)
		{
			// if we're here, we're navigating backwards
			ClearTransientState ();
		}
		#endregion

		#region AbstractAppPresenter implementation
		/// <summary>
		/// Overridable method to do work when the App is suspending.
		/// Call base impl as the first step.
		/// </summary>
		protected override void DoAppSuspendingWork ()
		{
			base.DoAppSuspendingWork ();
			UpdateFromView ();
			SaveTransientState ();
		}
		#endregion

		#region Event handlers
		private void OnDoReloadData ()
		{
			m_IsReloadingDataOnViewLoaded = true;
			ExecuteAsync (() => {
			              	m_Recipients = new List<String> ();
			              	LoadTransientState ();
			              	RefreshDataAndUpdateToView ();
			              	m_IsReloadingDataOnViewLoaded = false;
			              	View.EnableAllControls (true);
			              });
		}

		private void OnDoSelectCoordsFormat ()
		{
			View.EnableAllControls (false);
			ExecuteAsync (() =>
			              	{
			              		UpdateFromView ();
								SaveTransientState ();
			              		new SelectFormatPresenter ().Show (m_Recipients);
			              	});
		}
		#endregion

		#region helpers
		private void SaveTransientState ()
		{
			m_TransientState[RECIPIENTS] = m_Recipients.Print (";");
		}

		private void LoadTransientState ()
		{
			if (m_TransientState.ContainsKey (RECIPIENTS))
			{
				var recips = m_TransientState[RECIPIENTS] as String;
				if (!recips.IsNullOrEmptyOrBlank ())
				{
					m_Recipients = recips.Split (';');
				}
			}
		}

		private void ClearTransientState ()
		{
			if (m_TransientState.ContainsKey (RECIPIENTS))
			{
				m_TransientState[RECIPIENTS] = null;
				m_TransientState.Remove (RECIPIENTS);
			}
		}
		#endregion
	}
}
